#region

using Microsoft.Extensions.Options;
using SixLabors.Fonts;
using SixLabors.ImageSharp.Formats.Png;
using Vin.Extension.Cache;
using Vin.Extension.Captcha.Model;
using Vin.Extension.Captcha.Service.Interface;
using Vin.Tool.Attributes;
using Vin.Tool.Core.AssertCategory;

#endregion

namespace Vin.Extension.Captcha.Service.Implement.GenerateCaptcha;

public class VinGenerateCaptchaNormalService : VinBaseGenerateCaptchaService, IVinGenerateCaptchaService
{
    [Inject] private readonly IOptionsMonitor<VinCaptchaOption> _optionsMonitor = null!;

    private string CacheKey(string uuid) => _optionsMonitor.CurrentValue.CacheKey + uuid;

    public GenerateCodeModel GenerateCaptcha(char[] text, Font? font = null, int fontSize = 20, int width = 100,
        int height = 34)
    {
        // font ??= new FontCollection().AddSystemFonts().Families.Last().CreateFont(fontSize, FontStyle.Bold);
        font = SystemFonts.CreateFont(SystemFonts.Families.First().Name, fontSize, FontStyle.Bold);
        var uuid = Guid.NewGuid().ToString("N");
        var base64 = CreateImageBase64(width, height, text, font, fontSize, PngFormat.Instance, 2, -50, 50);
        CacheFactory.SetCache<string>(CacheKey(uuid), new string(text),
            TimeSpan.FromMinutes(_optionsMonitor.CurrentValue.Expire));
        return new GenerateCodeModel()
        {
            Base64 = base64,
            Uuid = uuid
        };
    }

    public GenerateCodeModel GenerateCaptcha(string text, Font? font = null, int fontSize = 20, int width = 100,
        int height = 34)
    {
        return GenerateCaptcha(text.ToCharArray(), font, fontSize, width, height);
    }

    public void ClearCaptcha(string? uuid)
    {
        if (uuid.IsNotNullOrWhiteSpace())
        {
            CacheFactory.RemoveCache(CacheKey(uuid!));
        }
    }

    public bool VerifyCaptcha(string uuid, string text)
    {
        var cacheKey = CacheKey(uuid);
        var cacheText = CacheFactory.GetCache<string>(cacheKey);
        if (cacheText == null)
        {
            return false;
        }

        CacheFactory.RemoveCache(cacheKey);
        return cacheText.Equals(text, StringComparison.OrdinalIgnoreCase) ||
               text.Equals(_optionsMonitor.CurrentValue.FixedCode, StringComparison.OrdinalIgnoreCase);
    }
}